package com.jeasonzhao.report.msg;

import java.util.Locale;

import com.jeasonzhao.commons.basic.StringPair;
import com.jeasonzhao.commons.basic.StringPairCollection;
import com.jeasonzhao.commons.utils.Algorithms;

public class LocalizationManager
{
    private boolean m_isCaseSenstive = false;
    private static class _Item
    {
        private java.util.Hashtable<String,String> items = null;
        private void add(String strLng,String msg)
        {
            if(Algorithms.isEmpty(strLng) || Algorithms.isEmpty(msg))
            {
                return;
            }
            if(null == items)
            {
                items = new java.util.Hashtable<String,String>();
            }
            strLng = strLng.trim().toLowerCase();
            items.put(strLng,msg);
        }

        private String get(String strLng)
        {
            if(null == items)
            {
                return null;
            }
            if(Algorithms.isEmpty(strLng))
            {
                return this.getDefault();
            }
            else
            {
                return items.get(strLng.trim().toLowerCase());
            }
        }

        private String getDefault()
        {
            if(null == items || items.size() < 1)
            {
                return null;
            }
            java.util.Iterator<String> it = items.values().iterator();
            if(it == null || it.hasNext() == false)
            {
                return null;
            }
            else
            {
                return it.next();
            }
        }
    }

    private java.util.Hashtable<String,_Item> m_items = new java.util.Hashtable<String,_Item>();
    private static volatile LocalizationManager m_instance = null;
    private String m_strLanguage = null;
    private LocalizationManager()
    {
        Locale l = Locale.getDefault();
        m_strLanguage = l.toString();
    }

    public void setLanguage(String lang)
    {
        m_strLanguage = lang;
        if(Algorithms.isEmpty(lang))
        {
            Locale l = Locale.getDefault();
            m_strLanguage = l.toString();
        }
    }

    public boolean isCaseSenstive()
    {
        return m_isCaseSenstive;
    }

    public void setCaseSenstive(boolean isCaseSenstive)
    {
        this.m_isCaseSenstive = isCaseSenstive;
    }

    public static LocalizationManager getInstance()
    {
        if(null == m_instance)
        {
            synchronized(LocalizationManager.class)
            {
                m_instance = new LocalizationManager();
            }
        }
        return m_instance;
    }

    private String alignKey(String s)
    {
        if(Algorithms.isEmpty(s))
        {
            return s;
        }
        else
        {
            s = s.trim();
            if(false == this.m_isCaseSenstive)
            {
                s = s.toLowerCase();
            }
            return s;
        }
    }

    /**
     * Get the localized String by key
     * @param languageFlag String the language key, if could not found the specified key, it will use the last one matched
     * @param strKey String The key of the message
     * @return String
     */
    protected String get(String strKey,String languageFlag)
    {
        strKey = alignKey(strKey);
        if(null == strKey)
        {
            return null;
        }
        _Item item = m_items.get(strKey);
        if(null == item)
        {
            return null;
        }
        else
        {
            return item.get(languageFlag);
        }
    }

    private java.util.HashSet<Class<?>> m_hasBeenHandledClasses = new java.util.HashSet<Class<?>>();
    public String get(Class<?> cls)
    {
        return get(cls,null);
    }

    public String get(Class<?> cls,String strField)
    {
        if(null == cls)
        {
            return null;
        }
        initByClass(cls);
        String strKey = cls.getName();
        if(Algorithms.notEmpty(strField))
        {
            strKey += "." + strField;
        }
        return get(strKey,this.m_strLanguage);
    }

    private void initByClass(Class<?> cls)
    {
        if(null == cls)
        {
            return;
        }
        try
        {
            if(m_hasBeenHandledClasses.contains(cls) == false)
            {
                if(Throwable.class.isAssignableFrom(cls))
                {
                    Message msg = (Message) cls.getAnnotation(Message.class);
                    if(null != msg)
                    {
                        addkeys(cls.getName(),msg);
                    }
                }
                else
                {
                    for(java.lang.reflect.Field f : cls.getDeclaredFields())
                    {
                        if(java.lang.reflect.Modifier.isStatic(f.getModifiers()))
                        {
                            f.setAccessible(true);
                            Message msg = f.getAnnotation(Message.class);
                            if(null != msg)
                            {
                                Object obj = f.get(null);
                                if(null != obj)
                                {
                                    String strKey = obj.toString();
                                    addkeys(cls.getName() + "." + strKey,msg);
                                }
                            }
                        }
                    }
                }
                m_hasBeenHandledClasses.add(cls);
            }
        }
        catch(IllegalAccessException ex)
        {
        }
        catch(IllegalArgumentException ex)
        {
        }
        catch(SecurityException ex)
        {
        }
    }

    private void addkeys(String key,Message msg)
    {
        if(null == key || null == msg)
        {
            return;
        }
        if(null != msg.encode() && msg.encode().trim().length() > 0)
        {
            StringPairCollection colls = StringPairCollection.from(msg.encode(),";",":");
            if(null != colls)
            {
                for(StringPair p : colls)
                {
                    this.add(key,p.getKey(),p.getName());
                }
            }
        }
        for(int n = 0;null != msg.value() && n < msg.value().length && (n + 1) < msg.value().length;n += 2)
        {
//            System.out.println(key+"["+msg.value()[n]+"]="+msg.value()[n+1]);
            this.add(key,msg.value()[n],msg.value()[n + 1]);
        }
    }

    public void remove(String strKey)
    {
        if(Algorithms.isEmpty(strKey))
        {
            return;
        }
        strKey = alignKey(strKey);
        m_items.remove(strKey);
    }

    public void add(String strKey,String languageFlag,String strValue)
    {
        if(Algorithms.isEmpty(strKey) || Algorithms.isEmpty(languageFlag) || Algorithms.isEmpty(strValue))
        {
            return;
        }
        strKey = alignKey(strKey);
        synchronized(m_items)
        {
            _Item item = m_items.get(strKey);
            if(null == item)
            {
                item = new _Item();
                m_items.put(strKey,item);
            }
            item.add(languageFlag,strValue);
        }
    }
}
